
`include "common_header.verilog"

//  *************************************************************************
//  File : fiform.v
//  ****************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized Reproduction or Use is Expressly Prohibited. 
//  Copyright (c) 2005 MoreThanIP
//  Designed by Francois Balay
//  fbalay@morethanip.com
//  ****************************************************************************
//  *            FIFO with Rate Matching Capability          
//  ****************************************************************************
//  Version    : $Id: fiform.v,v 1.9 2017/06/07 14:37:54 dk Exp $
//  ****************************************************************************

module fiform (

   reset_ln_clk,
   reset_xgmii_clk,
   jumbo_en,
   ln_clk,
  `ifdef USE_CLK_ENA
   ln_clk_ena,
  `endif
   ln_rxd,
   ln_rxc,
   fifo_fault,
   xgmii_clk,
  `ifdef USE_CLK_ENA
   xgmii_clk_ena,
  `endif
   xgmii_rxd,
   xgmii_rxc);

input   reset_ln_clk;           //  Global Reset - ln_clk Domain
input   reset_xgmii_clk;        //  Global Reset - xgmii_clk Domain
input   jumbo_en;               //  increase thresholds(=latency) to support jumbo frames
input   ln_clk;                 //  156MHz FIFO Line Clock
input   [63:0] ln_rxd;          //  XGMII Data
input   [7:0] ln_rxc;           //  XGMII Command Word
output  fifo_fault;             //  FIFO has internal error (Over/Underflow)
input   xgmii_clk;              //  156 XGMII Clock
output  [63:0] xgmii_rxd;       //  XGMII Data
output  [7:0] xgmii_rxc;        //  XGMII Command Word

`ifdef USE_CLK_ENA
input   ln_clk_ena;
input   xgmii_clk_ena;
`endif

reg     fifo_fault; 
wire    [63:0] xgmii_rxd; 
wire    [7:0] xgmii_rxc; 

wire    delete4_ok;             //  deletion of current lower column (31..0) possible
wire    idle_hi; 
wire    idle_lo; 
reg     idle_hi_d; 
wire    seq_hi; 
wire    seq_lo; 
reg     seq_hi_d; 
wire    wr_fail;
wire    wr_fail_reg2;  
wire    rd_fail; 

wire    vcc; 
assign  vcc = 1'b 1; 

//  determine if we can delete or insert idles after current 64 bit word 
//  --------------------------------------------------------------------

assign idle_lo = ln_rxd[31:0]  == 32'h 07070707 & ln_rxc[3:0] == 4'b 1111 ? 1'b 1 : 1'b 0; 
assign idle_hi = ln_rxd[63:32] == 32'h 07070707 & ln_rxc[7:4] == 4'b 1111 ? 1'b 1 : 1'b 0; 
assign seq_lo  = ln_rxd[7:0]   == 8'h 9C & ln_rxc[3:0]        == 4'b 0001 ? 1'b 1 : 1'b 0; 
assign seq_hi  = ln_rxd[39:32] == 8'h 9C & ln_rxc[7:4]        == 4'b 0001 ? 1'b 1 : 1'b 0; 

always @(posedge ln_clk or posedge reset_ln_clk)
   begin : p_insdel
   if (reset_ln_clk == 1'b 1)
      begin
      idle_hi_d  <= 1'b 0;   
      seq_hi_d   <= 1'b 0;   
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(ln_clk_ena == 1'b 1)
            begin
         `endif        
      
              idle_hi_d <= idle_hi;   
              seq_hi_d  <= seq_hi;   
      
         `ifdef USE_CLK_ENA
            end
         `endif      
      
      end
   end

   //  determine if deletion of lower column in current word is possible
   //  -----------------------------------------------------------------

   
assign delete4_ok = (idle_hi_d == 1'b 1 & idle_lo == 1'b 1 | 
                       idle_hi == 1'b 1 & idle_lo == 1'b 1 | 
                      seq_hi_d == 1'b 1 & seq_lo == 1'b 1 | 
                        seq_hi == 1'b 1 & seq_lo == 1'b 1 | 
                        seq_hi == 1'b 1 & idle_lo== 1'b 1 ) ? 1'b 1 : 1'b 0;


//  FIFO: Write is always enabled (XGMII), Read is dicated by the PCS TX
//  ---------------------------------------------------------------------

xgrm_fifo #(0) U_RMFF (

          .reset_wr_clk(reset_ln_clk),
          .reset_rd_clk(reset_xgmii_clk),
          .jumbo_en(jumbo_en),
          .wr_clk(ln_clk),
          `ifdef USE_CLK_ENA
           .wr_clk_ena(ln_clk_ena),
          `endif          
          .rd_clk(xgmii_clk),
          `ifdef USE_CLK_ENA
           .rd_clk_ena(xgmii_clk_ena),
          `endif           
          .wr_fail(wr_fail),
          .rd_fail(rd_fail),
          .ln_data(ln_rxd),
          .ln_control(ln_rxc),
          .ln_ena(vcc),
          .delete4_ok(delete4_ok),
          .out_dat(xgmii_rxd),
          .out_ctl(xgmii_rxc));

mtip_xsync #(1) U_SYWRFAIL (
        .data_in(wr_fail),
        .reset  (reset_xgmii_clk),
        .clk    (xgmii_clk),
        .data_s (wr_fail_reg2));

always @(posedge reset_xgmii_clk or posedge xgmii_clk)
   begin : xgmii_p
   if (reset_xgmii_clk == 1'b 1)
      begin
      fifo_fault   <= 1'b 0;
      end
   else
      begin

              if (rd_fail == 1'b 1 | wr_fail_reg2 == 1'b 1)
                 begin
        
           // Domain crossing: fault conditions last for several clock cycles
           // ---------------------------------------------------------------
           
                 fifo_fault <= 1'b 1;   
                 end
              else
                `ifdef USE_CLK_ENA
                if(xgmii_clk_ena == 1'b 1)
                `endif       
                 begin
                 fifo_fault <= 1'b 0;   
                 end
      
      end
   end

endmodule // module fiform